package com.cqc.jdk8.Jutil.stream;

import com.cqc.eb.UserEB;
import org.junit.Before;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * reduce()把流的元素合并成一个元素
 */
public class ReduceTest {

    List<UserEB> userEBList = null;

    @Before
    public void before() {
        this.getUserEBList();
    }

    @Test
    public void f1() {
        String[] arr = {"b", "c", "a", "d"};
        //reduce
        Optional<String> optional = Stream.of(arr)
                .sorted()
                .filter(str -> str.startsWith("Z"))
                .reduce((a, b) -> a + "#" + b);
        optional.ifPresent(System.out::println);

        String result = optional.orElse("x");
        System.out.println(result);
    }

    @Test
    public void f2() {
        String[] arr = {"b", "c", "a", "d"};
        Stream.of(arr)
                .sorted()
                .reduce((a, b) -> a + "#" + b)
                .ifPresent(System.out::println);
    }

    /**
     * Collectors.joining(..)可以实现 reduce 相同的效果
     */
    @Test
    public void f3() {
        String[] arr = {"b", "c", "a", "d"};
        //+arr=new String[]{};
        String result = Stream.of(arr)
                .sorted()
                .reduce((a, b) -> a + "#" + b)
                .orElseGet(() -> "");
        System.out.println("result=" + result);


        String result2 = Stream.of(arr)
                .sorted(Comparator.reverseOrder())
                .collect(Collectors.joining("+"));
        System.out.println("result2=" + result2);
    }

    /**
     * 规约求和的3种方式
     */
    @Test
    public void sum() {
        List<Integer> list = Arrays.asList(1, 2, 3);
        list.stream()
                .reduce((x, y) -> x + y)
                .ifPresent(System.out::println);

        list.stream()
                .reduce(Integer::sum)
                .ifPresent(System.out::println);

        Integer sum = list.stream()
                .reduce(0, Integer::sum);
        System.out.println(sum);
    }

    /**
     * 求最大值的3种方式
     */
    @Test
    public void max() {
        List<Integer> list = Arrays.asList(1, 2, 3);
        list.stream()
                .reduce((x, y) -> x > y ? x : y)
                .ifPresent(System.out::println);

        list.stream()
                .reduce(Integer::max)
                .ifPresent(System.out::println);

        Integer sum = list.stream()
                .reduce(10, Integer::max);
        System.out.println(sum);
    }

    /**
     * reduce求和的几种写法
     */
    @Test
    public void sum2() {
        //写法1
        userEBList.stream()
                .map(x -> x.getSalary())
                .reduce((x, y) -> x + y)
                .ifPresent(System.out::println);

        //写法2
        userEBList.stream()
                .map(UserEB::getSalary)
                .reduce(Double::sum)
                .ifPresent(System.out::println);

        //写法3， identity就是第一个参数的值，类型也必须一样
        Double result = userEBList.stream()
                .reduce(0.1d, (identity, p) -> identity += p.getSalary(), (sum1, sum2) -> sum1 + sum2);
        System.out.println(result);
        //写法4
        Double result2 = userEBList.stream()
                .reduce(0.1d, (identity, p) -> identity += p.getSalary(), Double::sum);
        System.out.println(result2);
    }

    /**
     * reduce求最大值的几种写法
     */
    @Test
    public void max2() {
        //写法1
        userEBList.stream()
                .map(x -> x.getSalary())
                .reduce((x, y) -> x > y ? x : y)
                .ifPresent(System.out::println);

        //写法2
        userEBList.stream()
                .map(UserEB::getSalary)
                .reduce(Double::max)
                .ifPresent(System.out::println);

        //写法3， identity就是第一个参数的值，类型也必须一样
        Double result = userEBList.stream()
                .reduce(0.1d, (identity, p) -> identity > p.getSalary() ? identity : p.getSalary(), (x, y) -> x > y ? x : y);
        System.out.println(result);
        //写法4
        Double result2 = userEBList.stream()
                .reduce(0.1d, (identity, p) -> identity > p.getSalary() ? identity : p.getSalary(), Double::max);
        System.out.println(result2);
    }

    private void getUserEBList() {
        userEBList = new ArrayList<>();
        userEBList.add(new UserEB("刘诗诗", 33, 2000, "女", "北京"));
        userEBList.add(new UserEB("刘亦菲", 33, 2500, "女", "武汉"));
        userEBList.add(new UserEB("古力娜扎", 30, 1500, "女", "乌鲁木齐"));
    }
}
